<?php

namespace Dls\Entity\V0\Grid;

use Closure;
use Dls\Entity\V0\FormatterAbstract;
use Dls\Entity\V0\Grid;
use Dls\Entity\V0\Interfaces\Searchable;
use Illuminate\Database\Eloquent\Model as Eloquent;

class Column
{

    /**
     * Name of column.
     *
     * @var string
     */
    protected $name;

    /**
     * Label of column.
     *
     * @var string
     */
    protected $label;

    /**
     * Original value of column.
     *
     * @var mixed
     */
    protected $original;

    /**
     * Is column sortable.
     *
     * @var bool
     */
    protected $sortable = false;

    /**
     * Sort arguments.
     *
     * @var array
     */
    protected $sort = [];

    /**
     * Attributes of column.
     *
     * @var array
     */
    protected $attributes = [];

    /**
     * Relation name.
     *
     * @var bool
     */
    protected $relation = false;

    /**
     * Relation column.
     *
     * @var string
     */
    protected $relationColumn;

    /**
     * 单个字段处理的callback
     *
     * @var Closure
     */
    protected $displayCallbacks = null;

    /**
     * @var
     */
    protected static $model;
    /**
     * @var Grid
     */
    protected $grid;

    /**
     * 用于修饰列的前端支持
     *
     * @var Th
     */
    protected $th;

    /**
     * 查询器
     *
     * @var Searchable
     */
    protected $searcher;

    /**
     * 支持替换返回值
     *
     * @var Replace string
     */
    protected $replace = '';

    /**
     * 是否忽略查询字段
     *
     * @var bool
     */
    protected $ignore = false;

     /**
     * 是否展示
     *
     * @var bool
     */
    protected $hide = false;

    /**
     * is need to group by
     *
     * @var string
     */
    protected $groupBy = false;

    /**
     * formatter the name
     *
     * @var null
     */
    protected $formatter = null;

    /**
     * 别名
     *
     * @var null
     */
    protected $alias = null;

    protected $htmlClass = [];

    /**
     * @param string $name
     * @param string $label
     */
    public function __construct($name, $label = null)
    {
        $this->name = $name;
        $this->label = $label;
    }


    /**
     * Set grid instance for column.
     *
     * @param Grid $grid
     */
    public function setGrid(Grid $grid)
    {
        $this->grid = $grid;

        $this->setModel($grid->model()->eloquent());
    }

    /**
     * Set model for column.
     *
     * @param $model
     */
    public function setModel($model)
    {
        if (is_null(static::$model) && ($model instanceof Eloquent)) {
            static::$model = $model->newInstance();
        }
    }

    /**
     * Get name of this column.
     *
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }


    /**
     * Get label of the column.
     *
     * @return mixed
     */
    public function getLabel()
    {
        return $this->label;
    }

    /**
     * Set relation.
     *
     * @param string $relation
     * @param string $relationColumn
     *
     * @return $this
     */
    public function setRelation($relation, $relationColumn = null)
    {
        $this->relation = $relation;
        $this->relationColumn = $relationColumn;

        return $this;
    }

    /**
     * If this column is relation column.
     *
     * @return bool
     */
    protected function isRelation()
    {
        return (bool) $this->relation;
    }

    /**
     * Get the query string variable used to store the sort.
     *
     * @return array
     */
    public function getSort()
    {
        return $this->sort;
    }

    /**
     * Set the column sort
     *
     * @param string $direction
     * @param null $name
     * @return $this
     */
    public function setSort($direction = 'desc', $name = null)
    {
        $this->sort = [
            'column' => $name ?? $this->name,
            'direction' => $direction
        ];

        return $this;
    }

    /**
     * 获取查询器
     *
     * @return Searchable|null
     */
    public function getSearcher()
    {
        return $this->searcher;
    }

    /**
     * 设置查询器
     *
     * @param Searchable $searcher
     * @return Column
     */
    public function setSearcher(Searchable $searcher)
    {
        $this->searcher = $searcher;
        return $this;
    }

    /**
     * @return Replace
     */
    public function getReplace()
    {
        return $this->replace;
    }

    /**
     * @param Replace $replace
     * * @return Column
     */
    public function setReplace(Replace $replace)
    {
        $this->replace = $replace;
        return $this;
    }

    /**
     * Add a display callback.
     *
     * @param Closure $callback
     *
     * @return Column
     */
    public function display(Closure $callback)
    {
        $this->displayCallbacks = $callback;

        return $this;
    }

    /**
     * 判断当前列是否需要转换
     *
     * @return bool
     */
    public function hasDisplay()
    {
        return ! is_null($this->displayCallbacks);
    }

    /**
     * handle by model
     *
     * @param $item
     * @return Column
     */
    public function with($value)
    {
        if ($this->displayCallbacks instanceof \Closure) {
            return $this->displayCallbacks->call($this, $value);
        }
        return $value;
    }

    /**
     * set group is true
     *
     * @return Column
     */
    public function groupBy()
    {
        $this->groupBy = true;
        return $this;
    }

    /**
     * get group status
     *
     * @return string
     */
    public function getGroupBy()
    {
        return $this->groupBy;
    }

    /**
     * 设置隐藏
     *
     * @return Column
     */
    public function hide()
    {
        $this->hide = true;
        return $this;
    }

    /**
     * 是否可展示
     *
     * @return bool
     */
    public function isHide()
    {
        return $this->hide;
    }

    /**
     * @return FormatterAbstract|null
     */
    public function getFormatter()
    {
        return $this->formatter;
    }

    /**
     * @param null $formatter
     */
    public function setFormatter(FormatterAbstract $formatter = null)
    {
        $this->formatter = $formatter;
        return $this;
    }

    /**
     * @return null
     */
    public function getAlias()
    {
        return $this->alias ?? $this->getName();
    }

    /**
     * @param null $alias
     */
    public function alias($alias)
    {
        $this->alias = $alias;
        return $this;
    }

    /**
     * @return $this
     */
    public function ignore()
    {
        $this->ignore = true;
        return $this;
    }

    /**
     * @return bool
     */
    public function getIgnore()
    {
        return $this->ignore;
    }


    /**
     * @return array
     */
    public function getHtmlClass(): string
    {
        return implode(' ', $this->htmlClass);
    }

    /**
     * @param array $htmlClass
     */
    public function setHtmlClass(array $htmlClass)
    {
        $this->htmlClass = $htmlClass;
        return $this;
    }

    /**
     * 设置可排序
     *
     * @return $this
     */
    public function sortable()
    {
        array_push($this->htmlClass, 'sort');
        return $this;
    }

    /**
     * Passes through all unknown calls to builtin displayer or supported displayer.
     *
     * Allow fluent calls on the Column object.
     *
     * @param string $method
     * @param array  $arguments
     *
     * @return $this
     */
    public function __call($method, $arguments)
    {
        if ($this->isRelation() && !$this->relationColumn) {
            $this->name = "{$this->relation}.$method";
            $this->label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);

            $this->relationColumn = $method;

            return $this;
        }
    }
}
